Skip to content

[docs] Document the Batcher and CacheKey features - #1728

Open
andrewnicols wants to merge 1 commit into
moodle:mainfrom
andrewnicols:MDL-82652
Open

andrewnicols wants to merge 1 commit into
moodle:mainfrom
andrewnicols:MDL-82652

Conversation

@andrewnicols

Copy link
Copy Markdown
Member

MDL-82652

Copilot AI balanced review requested due to automatic review settings October 15, 2026 22:15
@andrewnicols andrewnicols added the blocked-by-tracker This issue is blocked by an issue in https://tracker.moodle.org/ label Oct 15, 2026
@netlify

netlify Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for moodledevdocs ready!

Name Link
🔨 Latest commit b912734
🔍 Latest deploy log https://app.netlify.com/projects/moodledevdocs/deploys/6ae4126323aa9d57d4f910ef
😎 Deploy Preview https://deploy-preview-1728--moodledevdocs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The documented URLs and minimum-version guidance need correction before developers can reliably use the examples.

3 open findings
What changed in this PR

Adds developer guides for request batching and cacheable routes in Moodle’s REST API.

Changes:

  • Documents automatic and manual core/fetch batching.
  • Explains route cache lifetimes, cache keys, headers, and batching interactions.
File Description
docs/​guides/​javascript/​ajax/​batcher.md Explains batching usage and configuration.
docs/​apis/​subsystems/​routing/​caching.md Documents cacheable routes and JavaScript requests.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

- Performance
---

<Since version="6.0" issueNumber="MDL-82652" />

```php title="A cacheable route"
#[\core\router\route(
path: '/strings/{language}/{component}[/{identifier:.*}]',
Comment on lines +41 to +42
/api/rest/v2/strings/en/core # No cache key - not cached
/api/rest/v2/cachekey:1737584047/strings/en/core # Cacheable

`cachelifetime` accepts any relative time string understood by [`DateInterval::createFromDateString()`](https://www.php.net/manual/en/dateinterval.createfromdatestring.php), for example `'90 days'`.

```php title="A cacheable route"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add cookies: false to the example? Plugin developers will copy it, and without it they'd hit the same bug the strings route had: every request starts a session, and proxies won't cache a response that sets a cookie.

```js
import Fetch from 'core/fetch';

const response = await Fetch.performGet('core', `strings/en/core`, {cachekey: M.cfg.jsrev});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- {cachekey: M.cfg.jsrev}
+ {cachekey: M.cfg.langrev}

As the code has at stringUtils.ts:156,194

Requests made with a `cachekey` (see [route caching](../../../apis/subsystems/routing/caching.md)) are sent individually, even via a batcher. Hiding them inside a generic `$batch` request would prevent browsers and reverse proxies caching each URL.

```js
const response = await Fetch.getBatcher().performGet('core', 'strings/en/core', {cachekey: M.cfg.jsrev});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- {cachekey: M.cfg.jsrev}
+ {cachekey: M.cfg.langrev}

As the code has at stringUtils.ts:156,194

/api/rest/v2/cachekey:1737584047/strings/en/core # Cacheable
```

Because the cache key forms part of the URI, changing it (typically by using the current JavaScript/theme revision) invalidates every cached copy of the resource. You do not need to declare the parameter yourself.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion:

- Because the cache key forms part of the URI, changing it (typically by using the current JavaScript/theme revision) invalidates every cached copy of the resource.
+ Because the cache key forms part of the URI, changing it invalidates every cached copy of the resource. Use the revision that changes with the resource: `M.cfg.langrev` for strings, `M.cfg.templaterev` for templates.


:::danger

Responses are cached as `public` and `immutable`. Only use `cachelifetime` for routes whose response is identical for every user and which never contains private data.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest adding to the danger note:

  Responses are cached as `public` and `immutable`. Only use `cachelifetime` for routes whose response is identical for every user and which never contains private data.
+
+ Anything the response varies by, such as the language or the theme, must be part of the path. Caches store responses by URL, so a value sent in a request header is ignored, and every user would get whichever version was requested first.

## Behaviour notes {/* #behaviour-notes */}

- If a batch contains a single request, the batch endpoint is _not_ used; it is sent as a normal request.
- The queue is flushed automatically once it holds more than 20 requests.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check is now >= 20, so a batch holds at most 20 requests rather than "more than 20"

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked-by-tracker This issue is blocked by an issue in https://tracker.moodle.org/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants